package com.bluebench.bigul.domain;

import java.util.ArrayList;
import java.util.List;

import com.bluebench.bigul.exception.GraphicInitializationException;
import com.bluebench.bigul.service.resolver.DefaultExpressionResolver;
import com.bluebench.bigul.utility.annotation.Assign;

public class Element extends Tag{
	
	@Assign("element")
	private List<Element> elements;
	@Assign("attribute")
	private List<Attribute> attributes;	
	private Invocation invocation;	
	
	
	public Element() throws GraphicInitializationException {
		this.setElementType(ElementType.ELEMENT);
		elements = new ArrayList<Element>();
		attributes = new ArrayList<Attribute>();
		setResolver(DefaultExpressionResolver.getInstance(DefaultExpressionResolver.ELEMENT_RESOLVER));
	}
	
	public Element(int resolver) throws GraphicInitializationException {
		this.setElementType(ElementType.ELEMENT);
		elements = new ArrayList<Element>();
		attributes = new ArrayList<Attribute>();
		setResolver(DefaultExpressionResolver.getInstance(resolver));
	}
	
	public class Attribute extends Tag{
		@Assign("parameter")
		private List<Parameter> parameters;
		private List<Attribute> attributes;
		private boolean isChained;

		public Attribute() {
			this.setElementType(ElementType.ATTRIBUTE);
			parameters = new ArrayList<Parameter>();
			attributes = new ArrayList<Attribute>();
			/*setResolver(GenericExpressionResolver.getInstance(ElementType.ATTRIBUTE));*/
		}
		
		public Attribute(int resolver) throws GraphicInitializationException {
			this.setElementType(ElementType.ATTRIBUTE);
			parameters = new ArrayList<Parameter>();
			setResolver(DefaultExpressionResolver.getInstance(resolver));
		}
		
		
		public List<Parameter> getParameters() {
			return parameters;
		}

		public void setParameters(List<Parameter> parameters) {
			this.parameters = parameters;
		}
		
		public void addParameter(Parameter parameter){
			parameters.add(parameter);
		}
		
		public void addParameter(Object o){
			Parameter p = new Parameter();
			p.setValue(o);
			if(o instanceof Element){
				Element el = (Element)o; 
				p.setType(el.getType());
			}
			
			this.parameters.add(p);
		}
		
		public Parameter getLastParameter(){
			return (parameters.size()>0) ? parameters.get(parameters.size()-1) : null;
		}
		
		@Override
		public String toString() {		
			return this.getId();
		}

		public List<Attribute> getAttributes() {
			return attributes;
		}

		public void setAttributes(List<Attribute> attributes) {
			this.attributes = attributes;
		}
		
		public boolean addAttribute(Attribute attribute){
			isChained=true;
			return attributes.add(attribute);
		}

		public boolean isChained() {
			return isChained;
		}

		public void setChained(boolean isChained) {
			this.isChained = isChained;
		}

		public boolean hasNext() {
			if(isChained){
				if(attributes!=null && (!attributes.isEmpty())){
					return true;
				}
			}
			return false;
		}
	
	}
	
	public class Parameter extends Tag{
		@Assign("element")
		Object value;
		boolean isCollection; //if this parameter holds collection of parameter values
		boolean isNested; //if this parameter holds a nested element
		boolean isFormatted;

		public Parameter() {
			this.setElementType(ElementType.PARAMETER);
			/*setResolver(GenericExpressionResolver.getInstance(ElementType.PARAMETER));*/
		}
		
		public Parameter(int resolver) throws GraphicInitializationException {
			this.setElementType(ElementType.PARAMETER);
			setResolver(DefaultExpressionResolver.getInstance(resolver));
		}
		
		public Object getValue() {
			return value;
		}

		public void setValue(Object value) {
			if(value instanceof ArrayList){
				isCollection = true;
			}else{
				isCollection = false;
			}
			this.value = value;
		}
		
		public boolean addValue(Object value){
			if(this.value instanceof ArrayList){
				((ArrayList)this.value).add(value);
				return true;
			}else{
				return false;
			}
		}
		
		@Override
		public String toString() {
			return this.getId();
		}

		public boolean isCollection() {
			return isCollection;
		}

		public void setCollection(boolean isCollection) {
			this.isCollection = isCollection;
		}

		public boolean isNested() {
			return isNested;
		}

		public void setNested(boolean isNested) {
			this.isNested = isNested;
		}

		public boolean isFormatted() {
			return isFormatted;
		}

		public void setFormatted(boolean isFormatted) {
			this.isFormatted = isFormatted;
		}
	}

	public List<Element> getElements() {
		return elements;
	}

	public void setElements(List<Element> elements) {
		this.elements = elements;
	}

	public List<Attribute> getAttributes() {
		return attributes;
	}

	public void setAttributes(List<Attribute> attributes) {
		this.attributes = attributes;
	}

	public Invocation getInvocation() {
		return invocation;
	}

	public void setInvocation(Invocation invocation) {
		this.invocation = invocation;
	}
	
	public void addElement(Element element){
		elements.add(element);
	}
	
	public void addAttribute(Attribute attribute){
		attributes.add(attribute);
	}
	
	public void addAttributes(List<Attribute> attributes){
		//this.attributes.addAll(attributes);
		this.attributes.addAll(0,attributes);
	}
	
	public Attribute getLastAttribute(){
		return (attributes.size()>0) ? attributes.get(attributes.size()-1) : null;
	}	
	
	@Override
	public String toString() {
		if(getId()!=null){
			return getId();
		}
		return getName();
	}
	
}
